package com.hulk.rpc.loadbalance.impl;

import cn.hutool.core.net.NetUtil;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.hulk.rpc.loadbalance.LoadBalance;
import com.hulk.rpc.loadbalance.VirtualWeightable;
import com.hulk.rpc.loadbalance.Weightable;

import java.util.TreeMap;

/**
 * @author xuxukang
 * @date 2019-03-27 23:02
 */
public class ConsistentHashLoadBalance<T extends Weightable> extends LoadBalance<T> {

  private static final int VIRTUAL_NODE_NUM = 5;
  private TreeMap<Integer, T> consistentHashResources = new TreeMap<>();

  @Override
  public T select() {
    String localhostStr = NetUtil.getLocalhostStr();
    HashCode hashCode = Hashing.goodFastHash(32).hashBytes(localhostStr.getBytes());

    return consistentHashResources.get(hashCode.hashCode());
  }

  @Override
  public void clean() {
    initConsistentHashResources();
  }

  private void initConsistentHashResources() {
    VirtualWeightable virtualWeightable;
    for (T resource : resources) {
      for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
        virtualWeightable = new VirtualWeightable<>().setVirtualId(i)
                .setResource(resource);
        consistentHashResources.put(virtualWeightable.hashCode(), resource);
      }
    }
  }

}
